package com.woniuxy.book.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.woniuxy.book.entity.BookInfo;
import com.woniuxy.book.entity.PageInfo;
import com.woniuxy.book.entity.UserInfo;
import com.woniuxy.book.exception.bookinfo.BookInfoException;
import com.woniuxy.book.exception.bookinfo.BookInfoExceptionCode;
import com.woniuxy.book.exception.userinfo.UserInfoException;
import com.woniuxy.book.exception.userinfo.UserInfoExceptionCode;
import com.woniuxy.book.mapper.BookInfoMapper;
import com.woniuxy.book.mapper.UserInfoMapper;
import com.woniuxy.book.param.userinfo.CompleteUserParam;
import com.woniuxy.book.param.userinfo.UserLoginParam;
import com.woniuxy.book.param.userinfo.UserRegisterParam;
import com.woniuxy.book.service.UserInfoService;
import com.woniuxy.book.service.dto.*;
import com.woniuxy.book.util.*;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author li
 * @since 2024年2月09日
 */
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private SMSUtil smsUtil;

    @Resource
    private BookInfoMapper bookInfoMapper;

    //需要使用redisson时直接注入对象
    @Resource
    private RedissonClient redissonClient;

    @Resource
    private RabbitTemplate rabbitTemplate;


    //发送注册验证码操作
    @Override
    public void sendRegisterCode(String userPhone) throws Exception {
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.eq("user_phone", userPhone);
        UserInfo userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
        if (userInfo != null) {
            throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_USER_PHONE_EXISTS);
        }
        String codeMinuteKey = RedisKeyUtil.registerCodeMinute(userPhone);
        String codeKey = RedisKeyUtil.registerCodeKey(userPhone);
        String sendNumbersKey = RedisKeyUtil.sendNumbers(userPhone);
        send(codeMinuteKey, codeKey, sendNumbersKey, userPhone);
    }

    public void send(String codeMinuteKey, String codeKey, String sendNumbersKey, String userPhone) throws Exception {
        if (redisUtil.hasKey(codeMinuteKey)) {
            throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_REPEAT_SEND_ONEMINUTE);
        }
        String numberString = redisUtil.get(sendNumbersKey);
        if (numberString != null) {
            if (Integer.parseInt(numberString) == 5) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_FIVE_SEND_ONHOUR);
            }
        }
        //将手机号码保存到register.sendmessage这个队列中
        Map<String, Object> message = new HashMap<>();
        message.put("userPhone",userPhone);
        message.put("codeMinuteKey",codeMinuteKey);
        message.put("codeKey",codeKey);
        message.put("sendNumbersKey",sendNumbersKey);
        rabbitTemplate.convertAndSend("register.sendmessage",message);
    }

    //用户注册操作
    @Override
    public void register(UserRegisterParam param) throws Exception {
        RLock userNameLock = redissonClient.getFairLock(RedisKeyUtil.lockRegisterByUsername(param.getUserName()));
        RLock userPhoneLock = redissonClient.getFairLock(RedisKeyUtil.lockRegisterByUserPhone(param.getUserPhone()));
        //创建多资源锁
        RLock lock = redissonClient.getMultiLock(userNameLock, userPhoneLock);
        boolean isLock = lock.tryLock(15, TimeUnit.SECONDS);
        try {
            if (!isLock) {
                throw new Exception("服务器繁忙请稍后再试");
            }
            String codeKey = RedisKeyUtil.registerCodeKey(param.getUserPhone());
            String code = redisUtil.get(codeKey);
            //验证码是否存在或过期
            if (code == null) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_CODE_OUTDATE);
            }
            //验证码是否错误
            if (!code.equals(param.getCode())) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_CODE_ERROR);
            }
            //用户名防重
            QueryWrapper<UserInfo> userInfoQueryWrapper1 = new QueryWrapper<>();
            userInfoQueryWrapper1.eq("user_name", param.getUserName());
            UserInfo userInfo = userInfoMapper.selectOne(userInfoQueryWrapper1);
            if (userInfo != null) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_USER_USERNAME_EXISTS);
            }
            //号码是否已注册
            QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
            userInfoQueryWrapper.eq("user_phone", param.getUserPhone());
            userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
            if (userInfo != null) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_USER_PHONE_EXISTS);
            }
            UserInfo user = BeanUtil.toBean(param, UserInfo.class);
            user.setUserState(StateData.USER_INFO_STATE_NORMAL);
            userInfoMapper.insert(user);
            //删除redis中的验证码
            redisUtil.delete(codeKey);
        } finally {
            //释放锁
            if (userNameLock.isLocked()&&userPhoneLock.isLocked()) {
                lock.unlock();
            }
        }

    }

    @Override
    public void sendLoginCode(String userPhone) throws Exception {
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        userInfoQueryWrapper.eq("user_phone", userPhone);
        UserInfo userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
        if (userInfo == null) {
            throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_USER_PHONE_NOREGIST);
        }
        String codeMinuteKey = RedisKeyUtil.loginCodeMinute(userPhone);
        String codeKey = RedisKeyUtil.loginCodeKey(userPhone);
        String sendNumbersKey = RedisKeyUtil.loginSendNumbers(userPhone);
        send(codeMinuteKey, codeKey, sendNumbersKey, userPhone);
    }

    @Override
    public UserInfoDTO login(UserLoginParam param) {
        System.out.println(param.getUserPhone());
        System.out.println(param.getCode());
        UserInfo userInfo = null;
        QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<>();
        if ("".equals(param.getAccount()) && "".equals(param.getUserPass())) {
            String codeKey = RedisKeyUtil.loginCodeKey(param.getUserPhone());
            String code = redisUtil.get(codeKey);
            //验证码是否存在或过期
            if (code == null) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_CODE_OUTDATE);
            }
            //验证码是否错误
            if (!code.equals(param.getCode())) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_CODE_ERROR);
            }
            //验证电话是否注册
            userInfoQueryWrapper.eq("user_phone", param.getUserPhone());
            userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
            if (userInfo == null) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_USER_PHONE_NOREGIST);
            }
        } else {
            userInfoQueryWrapper.eq("user_phone", param.getAccount()).or().eq("user_name", param.getAccount());
            userInfo = userInfoMapper.selectOne(userInfoQueryWrapper);
            if (userInfo == null) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_USER_NOREGISTER);
            }
            if (!param.getUserPass().equals(userInfo.getUserPass())) {
                throw new UserInfoException(UserInfoExceptionCode.USER_INFO_EXCEPTION_PASSWORD_ERROR);
            }
        }
        UserInfoDTO userInfoDTO = BeanUtil.toBean(userInfo, UserInfoDTO.class);
        return userInfoDTO;
    }

    @Override
    public void collect(Integer userId, Integer bookId) {
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        //书籍状态是否异常
        if (bookInfo.getBookState() != StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_NORMAL);
        }
        //判断是否收藏过该书籍
        if (redisUtil.zscore(RedisKeyUtil.collectBook(userId), bookId + "") != null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_HAS_COLLECTED);
        }
        //redis中添加zset 键值对 使用当前的时间戳作为排序值
        redisUtil.zadd(RedisKeyUtil.collectBook(userId), bookId + "", new Date().getTime());
        //使收藏排行榜中该书籍的收藏量+1
        redisUtil.zincrby(RedisKeyUtil.collectBookRank(), bookId + "", 1);
    }

    @Override
    public void cancelCollect(Integer userId, Integer bookId) {
        //查询当前书籍信息
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        //书籍状态是否异常
        if (bookInfo.getBookState() != StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_NORMAL);
        }
        //判断是否收藏过该书籍
        if (redisUtil.zscore(RedisKeyUtil.collectBook(userId), bookId + "") == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_COLLECT);
        }
        redisUtil.zrem(RedisKeyUtil.collectBook(userId), bookId + "");
        //判断该书籍目前的收藏量
        if (redisUtil.zscore(RedisKeyUtil.collectBookRank(), bookId + "") > 1) {
            redisUtil.zincrby(RedisKeyUtil.collectBookRank(), bookId + "", -1);
        } else {
            redisUtil.zrem(RedisKeyUtil.collectBookRank(), bookId + "");
        }
    }

    @Override
    public PageInfo selectCollectRank(Integer pageNum, Integer pageSize, Integer userId) {
        //查询总条数
        Long total = redisUtil.zsize(RedisKeyUtil.collectBook(userId));
        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = 5;
        }
        Long pages = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
        ArrayList<CollectBookInfoDTO> list = new ArrayList<>();
        Set<String> set = redisUtil.revrange(RedisKeyUtil.collectBook(userId), pageNum, pageSize);
        if (set != null) {
            for (String bookId : set) {
                BookInfo bookInfo = bookInfoMapper.selectById(Integer.parseInt(bookId));
                CollectBookInfoDTO dto = BeanUtil.toBean(bookInfo, CollectBookInfoDTO.class);
                list.add(dto);
            }
        }
        PageInfo pageInfo = new PageInfo();
        pageInfo.setCurrent(Long.valueOf(pageNum));
        pageInfo.setList(list);
        pageInfo.setPages(pages);
        pageInfo.setSize(Long.valueOf(pageSize));
        pageInfo.setTotal(total);
        return pageInfo;
    }

    @Override
    public List<CollectRankDTO> selectCollectRankList() {
        Set<String> list = redisUtil.revrange(RedisKeyUtil.collectBookRank(), 1, 10);
        ArrayList<CollectRankDTO> collectRankDTOS = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (String bookId : list) {
                BookInfo bookInfo = bookInfoMapper.selectById(Integer.parseInt(bookId));
                Double score = redisUtil.zscore(RedisKeyUtil.collectBookRank(), bookId);
                CollectRankDTO collectRankDTO = BeanUtil.toBean(bookInfo, CollectRankDTO.class);
                collectRankDTO.setScore(score);
                collectRankDTOS.add(collectRankDTO);
            }
        }
        return collectRankDTOS;
    }

    @Override
    public void addShopping(Integer userId, Integer bookId, Integer number) {
        //先查询书籍信息
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState() != StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_NORMAL);
        }
        //判断该商品在购物车中是否存在
        if (redisUtil.zscore(RedisKeyUtil.userShoppingCar(userId), bookId + "") == null) {
            //购物车中不存在该商品
            redisUtil.zadd(RedisKeyUtil.userShoppingCar(userId), bookId + "", new Date().getTime());
            //将购物车详细信息已hash的形式保存到redis中
            HashMap<Object, Object> map = new HashMap<>();
            map.put("bookId", String.valueOf(bookId));
            map.put("bookShowname", bookInfo.getBookShowname());
            map.put("bookImage", bookInfo.getBookImage());
            map.put("bookPrice", String.valueOf(bookInfo.getBookPrice()));
            map.put("typeName", bookInfo.getTypeName());
            map.put("number", String.valueOf(number));
            map.put("checked", "true");
            redisUtil.hmset(RedisKeyUtil.shoppingCarInfo(userId, bookId), map);
        } else {
            //已经具备该商品
            redisUtil.hincrby(RedisKeyUtil.shoppingCarInfo(userId, bookId), "number", number);
        }
    }

    @Override
    public void addNumber(Integer userId, Integer bookId, Integer number) {
        //先查询书籍信息
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState() != StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_NORMAL);
        }
        if (redisUtil.zscore(RedisKeyUtil.userShoppingCar(userId), bookId + "") == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_SHOPPING_CAR_NOT_EXISTS);
        }
        redisUtil.hincrby(RedisKeyUtil.shoppingCarInfo(userId, bookId), "number", number);
    }

    @Override
    public void reduceNumber(Integer userId, Integer bookId, Integer number) {
        //先查询书籍信息
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState() != StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_NORMAL);
        }
        if (redisUtil.zscore(RedisKeyUtil.userShoppingCar(userId), bookId + "") == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_SHOPPING_CAR_NOT_EXISTS);
        }
        //判断当前的购物车数量
        Integer currentNumber = Integer.parseInt(redisUtil.hget(RedisKeyUtil.shoppingCarInfo(userId, bookId), "number").toString());
        if (currentNumber > number) {
            redisUtil.hincrby(RedisKeyUtil.shoppingCarInfo(userId, bookId), "number", -number);
        } else {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BUY_NUMBER_ATLEASTONE);
        }
    }

    @Override
    public PageInfo selectShoppingCar(Integer userId, Integer pageNum, Integer pageSize) throws Exception {

        if (pageNum == null) {
            pageNum = 1;
        }
        if (pageSize == null) {
            pageSize = 5;
        }
        //查询zset的长度即是购物车的总数量
        Long total = redisUtil.zsize(RedisKeyUtil.userShoppingCar(userId));
        //计算pages
        Long pages = total % pageSize == 0 ? total / pageSize : total / pageSize + 1;
        //先查询该用户购物车列表
        Set<String> set = redisUtil.revrange(RedisKeyUtil.userShoppingCar(userId), pageNum, pageSize);
        //该用户购物车中当前页的所有书籍编号
        ArrayList<Map<Object, Object>> list = new ArrayList<>();
        //循环查询每一个书籍编号对应的购物车信息
        if (set != null && set.size() > 0) {
            for (String bookId : set) {
                Map<Object, Object> car = redisUtil.hgetall(RedisKeyUtil.shoppingCarInfo(userId, Integer.parseInt(bookId)));
                list.add(car);
            }
        }

        ArrayList<ShoppingBookInfoDTO> shoppingBookInfoDTOS = new ArrayList<>();
        for (Map<Object, Object> objectObjectMap : list) {
            ShoppingBookInfoDTO shoppingBookInfoDTO = new ShoppingBookInfoDTO();
            Set<Object> objects = objectObjectMap.keySet();
            ShoppingBookDTO shoppingBookDTO = BeanMapUtils.mapToBean(objectObjectMap, ShoppingBookDTO.class);
            shoppingBookInfoDTO.setBookId(Integer.parseInt(shoppingBookDTO.getBookId()));
            shoppingBookInfoDTO.setBookImage(shoppingBookDTO.getBookImage());
            shoppingBookInfoDTO.setBookPrice(BigDecimal.valueOf(Double.parseDouble(shoppingBookDTO.getBookPrice())));
            shoppingBookInfoDTO.setBookShowname(shoppingBookDTO.getBookShowname());
            shoppingBookInfoDTO.setChecked(Boolean.valueOf(shoppingBookDTO.getChecked()));
            shoppingBookInfoDTO.setNumber(Integer.parseInt(shoppingBookDTO.getNumber()));
            shoppingBookInfoDTO.setTypeName(shoppingBookDTO.getTypeName());
            shoppingBookInfoDTOS.add(shoppingBookInfoDTO);
        }
        PageInfo pageInfo = new PageInfo();
        pageInfo.setCurrent(Long.valueOf(pageNum));
        pageInfo.setList(shoppingBookInfoDTOS);
        pageInfo.setPages(pages);
        pageInfo.setSize(Long.valueOf(pageSize));
        pageInfo.setTotal(total);
        return pageInfo;
    }

    @Override
    public void changeChecked(Integer bookId, Boolean checked, Integer userId) {
        //先查询书籍信息
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (bookInfo.getBookState() != StateData.BOOK_STATE_NORMAL) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_NORMAL);
        }
        if (redisUtil.zscore(RedisKeyUtil.userShoppingCar(userId), bookId + "") == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_SHOPPING_CAR_NOT_EXISTS);
        }
        String oldChecked = redisUtil.hget(RedisKeyUtil.shoppingCarInfo(userId, bookId), "checked").toString();
        if (oldChecked.equals(checked + "")) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_CHANGE_CHECKED_SAME);
        }
        redisUtil.hput(RedisKeyUtil.shoppingCarInfo(userId, bookId), "checked", checked + "");
    }

    @Override
    public ShoppingTotalDTO getTotalMoney(Integer userId) throws Exception {
        //查询zset的长度即是购物车的总数量
        Long total = redisUtil.zsize(RedisKeyUtil.userShoppingCar(userId));

        //先查询该用户购物车列表
        Set<String> set = redisUtil.revrange(RedisKeyUtil.userShoppingCar(userId), 1, total.intValue());
        //该用户购物车中当前页的所有书籍编号
        ArrayList<Map<Object, Object>> list = new ArrayList<>();
        //循环查询每一个书籍编号对应的购物车信息
        if (set != null && set.size() > 0) {
            for (String bookId : set) {
                Map<Object, Object> car = redisUtil.hgetall(RedisKeyUtil.shoppingCarInfo(userId, Integer.parseInt(bookId)));
                list.add(car);
            }
        }

        ArrayList<ShoppingMoneyDTO> shoppingMoneyDTOS = new ArrayList<>();
        BigDecimal totalMoney = new BigDecimal(0);
        for (Map<Object, Object> objectObjectMap : list) {
            ShoppingMoneyDTO shoppingMoneyDTO = new ShoppingMoneyDTO();
            Set<Object> objects = objectObjectMap.keySet();
            ShoppingBookDTO shoppingBookDTO = BeanMapUtils.mapToBean(objectObjectMap, ShoppingBookDTO.class);
            BookInfo bookInfo = bookInfoMapper.selectById(Integer.parseInt(shoppingBookDTO.getBookId()));
            if (shoppingBookDTO.getChecked().equals("true")&&bookInfo.getBookState()==StateData.BOOK_STATE_NORMAL) {
                BigDecimal money = (BigDecimal.valueOf(Double.parseDouble(shoppingBookDTO.getNumber()))).multiply(BigDecimal.valueOf(Double.parseDouble(shoppingBookDTO.getBookPrice())));
                totalMoney = totalMoney.add(money);
                shoppingMoneyDTO.setBookId(Integer.parseInt(shoppingBookDTO.getBookId()));
                shoppingMoneyDTO.setBookShowname(shoppingBookDTO.getBookShowname());
                shoppingMoneyDTO.setNumber(Integer.parseInt(shoppingBookDTO.getNumber()));
                shoppingMoneyDTO.setMoney(money);
                shoppingMoneyDTOS.add(shoppingMoneyDTO);
            }

        }
        ShoppingTotalDTO shoppingTotalDTO = new ShoppingTotalDTO();
        shoppingTotalDTO.setShoppingMoneyDTOS(shoppingMoneyDTOS);
        shoppingTotalDTO.setTotalMoney(totalMoney);
        return shoppingTotalDTO;
    }

    @Override
    public void delShpping(Integer bookId, Integer userId) {
        //先查询书籍信息
        BookInfo bookInfo = bookInfoMapper.selectById(bookId);
        if (bookInfo == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_BOOK_NOT_EXISTS);
        }
        if (redisUtil.zscore(RedisKeyUtil.userShoppingCar(userId), bookId + "") == null) {
            throw new BookInfoException(BookInfoExceptionCode.BOOK_INFO_EXCEPTION_SHOPPING_CAR_NOT_EXISTS);
        }
        redisUtil.zrem(RedisKeyUtil.userShoppingCar(userId),bookId+"");
        redisUtil.delete(RedisKeyUtil.shoppingCarInfo(userId, bookId));
    }

    @Override
    public UserInfo completeUserInfo(CompleteUserParam param, Integer userId) {
        UserInfo userInfo = userInfoMapper.selectById(userId);
        userInfo.setUserEmail(param.getUserEmail());
        userInfo.setUserNickname(param.getUserNickname());
        userInfoMapper.updateById(userInfo);
        return userInfo;
    }
}
